using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace CoTuong
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    /// 

    public class UndoData
    {
        public static int top;
        public int row, col, preRow, preCol;
        public bool QuanCoRemoved;
        public int ktQuanCo;
        public UndoData()
        {
            top++;
            ktQuanCo = 0;
            row = col = preRow = preCol = -1;
            QuanCoRemoved = false;
        }
    }

    public class VanCo : Microsoft.Xna.Framework.DrawableGameComponent
    {

        #region Sprites, Positions
        SpriteBatch spriteBatch;
        Texture2D banCo;
        Texture2D undo;
        Texture2D subMenu;
        public static Texture2D DiemDiChuyen;
        SpriteFont myFont;

        Vector2 ViTriBanCo;
        Vector2 ViTriUnDo;
        Vector2 ViTriSubMenu;
        #endregion

        public QuanLyQuanCo qlQuanCo;
        Game m_game;
        NetworkGame m_NetworkGame;
        SaveData m_saveData;

        public static int LuotDi;
        public static bool isPlaying;

        bool isUndoOnHover;
        bool isSubMenuOnHover;

        public static List<UndoData> undoData;

        public VanCo(Game game)
            : base(game)
        {
            m_game = game;
            KhoiTao();
            NapHinhAnh();
            isPlaying = true;
            // TODO: Construct any child components here
        }

        public VanCo(Game game, SaveData savedata) : base(game)
        {
            m_game = game;
            m_saveData = savedata;

            UndoData.top = -1;
            undoData = new List<UndoData>();
            NapHinhAnh();
            LuotDi = savedata.luotdi;
            qlQuanCo = new QuanLyQuanCo(m_game, m_saveData);
            isPlaying = true;
        }

        public VanCo(Game game, NetworkGame networkGame)
            : base(game)
        {
            m_game = game;
            m_NetworkGame = networkGame;
            LuotDi = 0;
            NapHinhAnh();
            UndoData.top = -1;
            undoData = new List<UndoData>();
            qlQuanCo = new QuanLyQuanCo(m_game, networkGame);
            isPlaying = true;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        private void KhoiTao()
        {
            // TODO: Add your initialization code here
            LuotDi = 0;   
            isUndoOnHover = false;
            isSubMenuOnHover = false;
            UndoData.top = -1;
            undoData = new List<UndoData>();
            qlQuanCo = new QuanLyQuanCo(m_game);
            
        }

        private void NapHinhAnh()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);

            //Nạp hình ảnh cho Texture2D
            banCo = Game.Content.Load<Texture2D>(@"Images\BanCo");
            undo = Game.Content.Load<Texture2D>(@"Images\undo");
            DiemDiChuyen = Game.Content.Load<Texture2D>(@"Images\Target");
            subMenu = Game.Content.Load<Texture2D>(@"Images\Button\MenuButton");
            myFont = Game.Content.Load<SpriteFont>(@"Font\myFont");

            //Lập vị trí hiển thị
            ViTriBanCo.X = 10;
            ViTriBanCo.Y = 10;
            ViTriUnDo.X = Game.Window.ClientBounds.Width - 60;
            ViTriUnDo.Y = 100;
            ViTriSubMenu.X = Game.Window.ClientBounds.Width - subMenu.Width * 2;
            ViTriSubMenu.Y = Game.Window.ClientBounds.Height / 2 - subMenu.Height / 2;
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            try
            {
                #region Xử lý hơ chuột
                if (Game1.mousePosition.X > ViTriUnDo.X && Game1.mousePosition.X < (ViTriUnDo.X + undo.Width)
                    && Game1.mousePosition.Y > ViTriUnDo.Y && Game1.mousePosition.Y < (ViTriUnDo.Y + undo.Height))
                    isUndoOnHover = true;
                else
                    isUndoOnHover = false;

                if (Game1.mousePosition.X > ViTriSubMenu.X && Game1.mousePosition.X < (ViTriSubMenu.X + subMenu.Width)
                    && Game1.mousePosition.Y > ViTriSubMenu.Y && Game1.mousePosition.Y < (ViTriSubMenu.Y + subMenu.Height))
                    isSubMenuOnHover = true;
                else
                    isSubMenuOnHover = false;
                #endregion

                #region Xử lý nút Undo
                if (Game1.mouseClickedPosition.X > ViTriUnDo.X && Game1.mouseClickedPosition.X < (ViTriUnDo.X + undo.Width)
                    && Game1.mouseClickedPosition.Y > ViTriUnDo.Y && Game1.mouseClickedPosition.Y < (ViTriUnDo.Y + undo.Height))
                {
                    //Undo ván cờ
                    Undo();
                }
                #endregion

                #region Xử lý nút Show SubMenu
                if (Game1.mouseClickedPosition.X > ViTriSubMenu.X && Game1.mouseClickedPosition.X < (ViTriSubMenu.X + subMenu.Width)
                    && Game1.mouseClickedPosition.Y > ViTriSubMenu.Y && Game1.mouseClickedPosition.Y < (ViTriSubMenu.Y + subMenu.Height))
                {
                    Game1.gameStateCurrent = (int)Game1.GameState.SubMenu;

                }
                #endregion

                qlQuanCo.Update(gameTime);
            }
            catch (Exception e)
            {
                Game1.errorMessage = e.Message;
            }
            base.Update(gameTime);
        }

        //cập nhật ván cờ khi chơi đấu LAN
        public void UpdateNetwork(GameTime gameTime)
        {

            try
            {
                if (m_NetworkGame.colorChess == LuotDi)
                {
                    #region Xử lý hơ chuột
                    if (Game1.mousePosition.X > ViTriUnDo.X && Game1.mousePosition.X < (ViTriUnDo.X + undo.Width)
                    && Game1.mousePosition.Y > ViTriUnDo.Y && Game1.mousePosition.Y < (ViTriUnDo.Y + undo.Height))
                        isUndoOnHover = true;
                    else
                        isUndoOnHover = false;
                    #endregion

                    #region Xử lý click nút Undo
                    if (Game1.mouseClickedPosition.X > ViTriUnDo.X && Game1.mouseClickedPosition.X < (ViTriUnDo.X + undo.Width)
                    && Game1.mouseClickedPosition.Y > ViTriUnDo.Y && Game1.mouseClickedPosition.Y < (ViTriUnDo.Y + undo.Height))
                    {
                        //Undo ván cờ
                        Undo();
                        foreach (LocalNetworkGamer gamer in NetworkGame.networkSession.LocalGamers)
                        {
                            PacketData data = new PacketData(0, 0, 0, 0, 0, true);
                            NetworkGame.packetWriter.Write(data.preCot);
                            NetworkGame.packetWriter.Write(data.preDong);
                            NetworkGame.packetWriter.Write(data.cot);
                            NetworkGame.packetWriter.Write(data.dong);
                            NetworkGame.packetWriter.Write(data.luotdi);
                            NetworkGame.packetWriter.Write(data.isUndo);
                            gamer.SendData(NetworkGame.packetWriter, SendDataOptions.InOrder);
                        }
                    }
                    #endregion

                    qlQuanCo.Update(gameTime);
                }
                else
                {
                    #region nhận thông tin từ đấu thủ
                    foreach (LocalNetworkGamer gamer in NetworkGame.networkSession.LocalGamers)
                    {
                        while (gamer.IsDataAvailable)
                        {
                            NetworkGamer sender;
                            gamer.ReceiveData(NetworkGame.packetReader, out sender);
                            if (sender.IsLocal)
                                continue;

                            int preCot = NetworkGame.packetReader.ReadInt32();
                            int preDong = NetworkGame.packetReader.ReadInt32();
                            int cot = NetworkGame.packetReader.ReadInt32();
                            int dong = NetworkGame.packetReader.ReadInt32();
                            int luotdi = NetworkGame.packetReader.ReadInt32();
                            bool isundo = NetworkGame.packetReader.ReadBoolean();

                            if (isundo)
                            {
                                Undo();
                                continue;
                            }

                            QuanLyQuanCo.ktQuanCo[preDong, preCot] = 0;
                            QuanLyQuanCo.ktQuanCo[dong, cot] = luotdi + 1;
                            LuotDi = (luotdi == 0 ? 1 : 0);

                            for (int i = 0; i < qlQuanCo.DanhSachQuanCo.Count; i++)
                            {

                                QuanCo q = qlQuanCo.DanhSachQuanCo[i];
                                if (q.getCot == preCot && q.getDong == preDong)
                                {
                                    q.setCot(cot);
                                    q.setDong(dong);
                                    Vector2 vitri;
                                    vitri.X = cot * (QuanCo.framesizeX + QuanCo.kcCot);
                                    vitri.Y = dong * (QuanCo.framesizeY + QuanCo.kcDong);
                                    q.setViTriQuanCo(vitri);
                                    qlQuanCo.DanhSachQuanCo[i] = q;

                                    UndoData data = new UndoData();
                                    data.preCol = preCot;
                                    data.preRow = preDong;
                                    data.col = cot;
                                    data.row = dong;
                                    data.ktQuanCo = luotdi + 1;
                                    VanCo.undoData.Add(data);

                                    for (int j = 0; j < qlQuanCo.DanhSachQuanCo.Count; j++)
                                    {
                                        if (i != j)
                                        {
                                            QuanCo p = qlQuanCo.DanhSachQuanCo[j];
                                            if (q.getCot == p.getCot && q.getDong == p.getDong && q.getQuan != p.getQuan)
                                            {
                                                //Lưu quân cờ bị ăn
                                                qlQuanCo.QuanCoRemoved.Add(p);

                                                //đánh dấu quân cờ bị ăn trong UndoData
                                                VanCo.undoData[UndoData.top].QuanCoRemoved = true;

                                                //Xóa quân cờ bị ăn trong danh sách
                                                qlQuanCo.DanhSachQuanCo.Remove(p);
                                            }

                                        }
                                    }



                                    break;
                                }
                            }
                        }
                    }
                    #endregion
                }

                #region Xử lý nút Menu
                if (Game1.mousePosition.X > ViTriSubMenu.X && Game1.mousePosition.X < (ViTriSubMenu.X + subMenu.Width)
                        && Game1.mousePosition.Y > ViTriSubMenu.Y && Game1.mousePosition.Y < (ViTriSubMenu.Y + subMenu.Height))
                    isSubMenuOnHover = true;
                else
                    isSubMenuOnHover = false;

                if (Game1.mouseClickedPosition.X > ViTriSubMenu.X && Game1.mouseClickedPosition.X < (ViTriSubMenu.X + subMenu.Width)
                    && Game1.mouseClickedPosition.Y > ViTriSubMenu.Y && Game1.mouseClickedPosition.Y < (ViTriSubMenu.Y + subMenu.Height))
                {

                }

                #endregion
            }
            catch (Exception e)
            {
                Game1.errorMessage = e.Message;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            Color myTransparentColor = new Color(255, 255, 255, 200);
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
            spriteBatch.Draw(banCo, ViTriBanCo, Color.White);
            if (isUndoOnHover == false)
                spriteBatch.Draw(undo, ViTriUnDo, myTransparentColor);
            else
                spriteBatch.Draw(undo, ViTriUnDo, Color.White);

            if (isSubMenuOnHover == false)
                spriteBatch.Draw(subMenu, ViTriSubMenu, myTransparentColor);
                //spriteBatch.Draw(subMenu, ViTriSubMenu, null, myTransparentColor, (float)Math.PI / 2, Vector2.Zero, 1, SpriteEffects.None, 0);
            else
                spriteBatch.Draw(subMenu, ViTriSubMenu, Color.White);


            spriteBatch.End();

            qlQuanCo.Draw(gameTime);

            base.Draw(gameTime);
        }

        //Vẽ hình ảnh ván đấu khi chơi đấu LAN
        public void DrawNetwork(GameTime gameTime)
        {
            Color myTransparentColor = new Color(255, 255, 255, 150);
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
            spriteBatch.Draw(banCo, ViTriBanCo, Color.White);
            if (isUndoOnHover == false)
                spriteBatch.Draw(undo, ViTriUnDo, myTransparentColor);
            else
                spriteBatch.Draw(undo, ViTriUnDo, Color.White);

            if (isSubMenuOnHover == false)
                spriteBatch.Draw(subMenu, ViTriSubMenu, myTransparentColor);
            else
                spriteBatch.Draw(subMenu, ViTriSubMenu, Color.White);

            spriteBatch.End();
            qlQuanCo.Draw(gameTime);
        }

        private void Undo()
        {
            if (UndoData.top >= 0)
            {
                int cot = VanCo.undoData[UndoData.top].col;
                int dong = VanCo.undoData[UndoData.top].row;
                int preCot = VanCo.undoData[UndoData.top].preCol;
                int preDong = VanCo.undoData[UndoData.top].preRow;
                int ktQuanCo = VanCo.undoData[UndoData.top].ktQuanCo;
                bool quanCoRemoved = VanCo.undoData[UndoData.top].QuanCoRemoved;
                
                for(int i = 0; i < qlQuanCo.DanhSachQuanCo.Count; i++)
                {
                    QuanCo q = qlQuanCo.DanhSachQuanCo[i];
                    if (q.getCot == cot && q.getDong == dong)
                    {
                        //Cập nhật lại vị trí cho quân cờ khi undo
                        q.setCot(preCot);
                        q.setDong(preDong);
                        Vector2 vitri; 
                        vitri.X = preCot *(QuanCo.framesizeX + QuanCo.kcCot);
                        vitri.Y = preDong *(QuanCo.framesizeY + QuanCo.kcDong);
                        q.setViTriQuanCo(vitri);
                        qlQuanCo.DanhSachQuanCo[i] = q;

                        //Undo tại vị trí quân cờ bị ăn
                        if (quanCoRemoved == true)
                        {
                            int top = qlQuanCo.QuanCoRemoved.Count - 1;
                            QuanCo p = qlQuanCo.QuanCoRemoved[top];
                            qlQuanCo.DanhSachQuanCo.Add(p);
                            qlQuanCo.QuanCoRemoved.RemoveAt(top);

                            if (p.getQuan == 0)
                                QuanLyQuanCo.ktQuanCo[dong, cot] = 1;
                            else
                                QuanLyQuanCo.ktQuanCo[dong, cot] = 2;
                        }
                        else
                            QuanLyQuanCo.ktQuanCo[dong, cot] = 0;
                        
                        //cập nhật lại bàn cờ o vị trí trước 
                        QuanLyQuanCo.ktQuanCo[preDong, preCot] = ktQuanCo;

                        //Cập nhật lượt đi khi undo
                        if (LuotDi == 0)
                            LuotDi = 1;
                        else
                            LuotDi = 0;
                        
                        break;
                    }
                }

                VanCo.undoData.RemoveAt(UndoData.top);
                UndoData.top--;

            }
        }
    }
}